// 简单题 

// 一、

1、你是如何理解JavaScript异步编程的？


单线程的理由

// JavaScript是单线程的，即同一时刻只能做一件事，采用这种方式是为了避免多线程之间dom操作产生的冲突，另一方面
// 却也导致了阻塞的可能性。阻塞就会造成性能的损耗，并且大大影响用户体验。

// 所以为了解决单线程阻塞的问题，让整个线程能够高效得运行下去，就有了异步编程

异步编程的历史

// 异步编程从回调函数到 Promise 到generator 到co 到async/await ，一代代更新，逐步得使异步编程越来越方便快捷。

// 回调函数的缺点是不利于代码的阅读和维护，个个部分之间高度耦合，流程很混乱。每个任务只能指定一个回调函数，也难以捕获异常。

// Promsie 不仅仅能避免回调函数，更可以统一捕获失败的原因

// generator是es6产生的，使用* 来生成迭代器，生成器函数和普通函数不一样，普通函数一旦调用会执行完，但是生成器函数可以暂停
// 生成器函数和托那个函数不一样，调用它不会立即执行。它会返回生成器的迭代器，迭代器是一个对象，每调用一次next就可以返回一个值对象
// { value: 'a', done: false }

// co是 TJ 大神结合了promise 和 生成器 的一个库，实际上还是帮助我们自动执行迭代器

// async await是语法糖，内部是generator+promise实现
// async函数就是将Generator函数的星号（*）替换成async，将yield替换成await

// 未来的异步函数await可能会脱离async


2、EventLoop是做什么的？

// EventLoop 是一个程序结构，它用于在单线程中等待和发送消息和实践。它能够解决单线程阻塞的问题，让整个线程可以高效运行你

// 在主线程执行的时候会产生堆、栈。栈中的任务执行是同步的，它们会调用DOM操作，ajax请求，定时器setTimeout，

// 这些请求都会被添加到消息队列中，只有当栈中的任务全部被执行完之后，主线程才会去执行消息队列中的任务。


3、消息队列都是做什么的？

// 有了事件循环，就可以接受新的任务了，不过此时的任务都来自线程内部，如果有 IO线程，比如鼠标点击事件，ajax 请求该如何处理呢？

// 通用的模式是消息队列。

// 消息队列是一个先进先出的队列数据结构，添加任务需要在队列的尾部，然后在头部取出，有了消息队列后我们的Event Loop 就比较完整了。

// 我们添加了一个消息队列，IO 线程中产生的新任务会添加到消息队列的尾部，主线程会循环得从消息队列头部中读取任务并执行


4、什么是宏任务？什么是微任务？

// 不同的异步任务被分为两类：微任务（micro task）和宏任务（macro task）。

// 在一个事件循环中，异步事件返回结果后会被放到一个任务队列中。然而，根据这个异步事件的类型，
// 这个事件实际上会被对应的宏任务队列或者微任务队列中去，当执行栈为空的时候，主线程会首先查看微任务中的事件，
// 如果微任务不是空的那么执行微任务中的事件，如果没有在宏任务中取出最前面的一个事件。
// 把对应的回调加入当前执行栈...如此反复，进入循环。




